package com.jeejio.train.util;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * Salt MD5 Util<br>
 * 
 * @author 白东洋<br>
 * Email: Programer.Monkey@gmail.com
 * 
 * @version 12.1.3.1 <br />
 * 20.2.10.1
 * 
 */
public class MD5 {

	/**
	 * 盐值长度
	 */
	private static final int SALT_LENGTH = 8;

	private MD5() {
	}

	/**
	 * 生成随机盐值
	 * 
	 * @param length
	 *            盐值长度
	 */
	private static String generalSalt(int length) {
		if (length < 1) {
			length = SALT_LENGTH;
		}
		StringBuffer salt = new StringBuffer();
		for (int i = 0; i < length; i++) {
			salt.append((char) (33 + (int) (Math.random() * (126 - 33 + 1))));
		}
		return salt.toString();
	}

	/**
	 * 32位标准 MD5 哈希
	 * 
	 * @param plainText
	 *            明文
	 * @return Result.hash 为 plainText 的 MD5 哈希值，同时 Result.salt 为 null。
	 */
	public static Result calc32(String plainText) throws NoSuchAlgorithmException {
		MessageDigest md = MessageDigest.getInstance("MD5");
		md.update(plainText.getBytes());
		byte b[] = md.digest();
		StringBuffer buf = new StringBuffer("");
		for (int offset = 0; offset < b.length; offset++) {
			buf.append(Integer.toHexString((0xFF & b[offset]) | 0xFFFFFF00).substring(6));
		}
		Result result = new Result();
		result.hash = buf.toString();
		return result;
	}

	/**
	 * 32 位 salt 加密
	 * 
	 * @param plainText
	 *            明文
	 * @return 索引 0 是密文<br>索引 1 是二次密钥(加盐值)
	 */
	public static Result salt32(String plainText) throws NoSuchAlgorithmException {
		String salt = generalSalt(SALT_LENGTH);
		Result result = calc32(plainText);
		result = calc32(result.hash + salt);
		result.salt = salt;
		return result;
	}

	/**
	 * 16 位标准 MD5 加密
	 * 
	 * @param plainText
	 *            明文
	 * @return 密文<br>
	 *         返回 Null 值则出现异常
	 */
	public static Result calc16(String plainText) throws NoSuchAlgorithmException {
		Result result = calc32(plainText);
		result.hash = result.hash.substring(8, 24);// 16位的加密
		return result;
	}

	/**
	 * 16 位 salt 加密
	 * 
	 * @param plainText
	 *            明文
	 * @return 索引 0 是密文，索引 1 是二次密钥
	 */
	public static Result salt16(String plainText) throws NoSuchAlgorithmException {
		String salt = generalSalt(SALT_LENGTH);
		Result result = calc16(plainText);
		result = calc16(result.hash + salt);
		result.salt = salt;
		return result;
	}

	public static class Result {
		public String hash = null;
		public String salt = null;
	}
}
